﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Index;
using NetTopologySuite.Index.Chain;
using NetTopologySuite.Index.Strtree;

namespace NetTopologySuite.Noding.Snapround
{
	public class MCIndexPointSnapper
	{
		public MCIndexPointSnapper(ISpatialIndex<MonotoneChain> index)
		{
			this._index = (STRtree<MonotoneChain>)index;
		}

		public bool Snap(HotPixel hotPixel, ISegmentString parentEdge, int hotPixelVertexIndex)
		{
			Envelope safeEnvelope = hotPixel.GetSafeEnvelope();
			MCIndexPointSnapper.HotPixelSnapAction hotPixelSnapAction = new MCIndexPointSnapper.HotPixelSnapAction(hotPixel, parentEdge, hotPixelVertexIndex);
			this._index.Query(safeEnvelope, new MCIndexPointSnapper.QueryVisitor(safeEnvelope, hotPixelSnapAction));
			return hotPixelSnapAction.IsNodeAdded;
		}

		public bool Snap(HotPixel hotPixel)
		{
			return this.Snap(hotPixel, null, -1);
		}

		private readonly STRtree<MonotoneChain> _index;

		private class QueryVisitor : IItemVisitor<MonotoneChain>
		{
			public QueryVisitor(Envelope env, MCIndexPointSnapper.HotPixelSnapAction action)
			{
				this._env = env;
				this._action = action;
			}

			public void VisitItem(MonotoneChain item)
			{
				item.Select(this._env, this._action);
			}

			private readonly Envelope _env;

			private readonly MCIndexPointSnapper.HotPixelSnapAction _action;
		}

		public class HotPixelSnapAction : MonotoneChainSelectAction
		{
			public HotPixelSnapAction(HotPixel hotPixel, ISegmentString parentEdge, int hotPixelVertexIndex)
			{
				this._hotPixel = hotPixel;
				this._parentEdge = parentEdge;
				this._hotPixelVertexIndex = hotPixelVertexIndex;
			}

			public bool IsNodeAdded
			{
				get
				{
					return this._isNodeAdded;
				}
			}

			public override void Select(MonotoneChain mc, int startIndex)
			{
				INodableSegmentString nodableSegmentString = (INodableSegmentString)mc.Context;
				if (this._parentEdge != null && nodableSegmentString == this._parentEdge && startIndex == this._hotPixelVertexIndex)
				{
					return;
				}
				this._isNodeAdded = this._hotPixel.AddSnappedNode(nodableSegmentString, startIndex);
			}

			private readonly HotPixel _hotPixel;

			private readonly ISegmentString _parentEdge;

			private readonly int _hotPixelVertexIndex;

			private bool _isNodeAdded;
		}
	}
}
